﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
//Xna
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
//Touchless
using TouchlessLib;

namespace Puzzle_3D
{
    class Puzzle_Menu
    {
        private static String IMAGEPATH = System.Threading.Thread.GetDomain().BaseDirectory + "Bilder";
        private static String MARKERPATH = System.Threading.Thread.GetDomain().BaseDirectory;
        private static int NUMBEROFPIECES = 6;
        public int MAXHIGHLIGHTS = 6;

        private TouchlessMgr touchlessMgr;
        private int _captureWidth, _captureHeight;
        private Texture2D cameraImage;
        private Puzzle_TouchlessMarker marker;
        private int cameraX, cameraY;
        private int screenPosX, screenPosY;

        //Menubilder und Optionen
        private Texture2D mainBackground;
        private Texture2D infoBackground;
        private Texture2D filterBackground;
        public bool isInfoMenu;
        public bool isOptionMenu;
        public bool isFilterMenu;
        public int filterOption;
        public Puzzle_MenuEntry[] menuEntries;
        public Puzzle_MenuEntry[] filterEntries;
        public Puzzle_MenuEntry[] backEntry;
        //Bilderauswahl
        private Texture2D highlightOptionTexture;
        public int highlightCount;
        //Anzahl der Bilderscreens (es werden immer 8 auf einer Seite dargestellt)
        public int imageScreens;
        public int showImageScreenNumber;
        public List<Puzzle_Image> imageList;
        private Puzzle_ImageProcessing imageProcessing;
        //Liste fuer die Bilder im Spiel
        public List<Puzzle_Image> gameImages;
        private List<Puzzle_PuzzlePiece> puzzleList;

        private bool drawCameraImage;

        private GraphicsDeviceManager graphicDeviceManager;
        private SpriteBatch spriteBatch;
        private ContentManager contentManager;
        private Puzzle rootPointer;

        private Puzzle_TouchlessGestures gestures;

        public Puzzle_Menu(Puzzle _root, TouchlessMgr _mgr)
        {
            this.rootPointer = _root;
            this.graphicDeviceManager = this.rootPointer.getGraphics();
            this.spriteBatch = this.rootPointer.getSpriteBatch();
            this.contentManager = this.rootPointer.Content;
            
            //Menu-Texturen
            this.mainBackground = this.contentManager.Load<Texture2D>("Graphic\\Menu");
            this.filterBackground = this.mainBackground;
            this.infoBackground = this.contentManager.Load<Texture2D>("Graphic\\InfoBG");
            this.isOptionMenu = this.isFilterMenu = this.isInfoMenu = false;

            //Highlight-Textur und Rectangle und Bilderliste
            this.highlightCount = 0;
            this.highlightOptionTexture = this.contentManager.Load<Texture2D>("Graphic\\selected");
            this.imageList = new List<Puzzle_Image>();
            this.gameImages = new List<Puzzle_Image>();
            this.puzzleList = new List<Puzzle_PuzzlePiece>();
            this.imageProcessing = new Puzzle_ImageProcessing(this.rootPointer);
            this.filterOption = 0;
            this.imageScreens = 0;
            this.showImageScreenNumber = 1;
            this.initImagesFromFolder();

            //Menu-Eintraege
            this.backEntry = new Puzzle_MenuEntry[1];
            this.backEntry[0] = new Puzzle_MenuEntry("Back", new Vector2(0, 517), this.contentManager.Load<Texture2D>("Graphic\\zurueck"), this.contentManager.Load<Texture2D>("Graphic\\zurueck_hover"));
            //Hauptmenu
            this.menuEntries = new Puzzle_MenuEntry[5];
            this.menuEntries[0] = new Puzzle_MenuEntry("Start", new Vector2(0, 157), this.contentManager.Load<Texture2D>("Graphic\\starten"), this.contentManager.Load<Texture2D>("Graphic\\starten_hover"));
            this.menuEntries[1] = new Puzzle_MenuEntry("Auswahl", new Vector2(0, 247), this.contentManager.Load<Texture2D>("Graphic\\bilder"), this.contentManager.Load<Texture2D>("Graphic\\bilder_hover"));
            this.menuEntries[2] = new Puzzle_MenuEntry("Filter", new Vector2(0, 337), this.contentManager.Load<Texture2D>("Graphic\\filter"), this.contentManager.Load<Texture2D>("Graphic\\filter_hover"));
            this.menuEntries[3] = new Puzzle_MenuEntry("Info", new Vector2(0, 427), this.contentManager.Load<Texture2D>("Graphic\\Info"), this.contentManager.Load<Texture2D>("Graphic\\info_hover"));
            this.menuEntries[4] = new Puzzle_MenuEntry("Exit", new Vector2(0, 517), this.contentManager.Load<Texture2D>("Graphic\\beenden"), this.contentManager.Load<Texture2D>("Graphic\\beenden_hover"));
            //Filtermenu
            this.filterEntries = new Puzzle_MenuEntry[3];
            this.filterEntries[0] = new Puzzle_MenuEntry("Filter1", new Vector2(55, 190), this.contentManager.Load<Texture2D>("Graphic\\BlackWhite"), this.contentManager.Load<Texture2D>("Graphic\\BlackWhite_hover"));
            this.filterEntries[1] = new Puzzle_MenuEntry("Filter2", new Vector2(305, 190), this.contentManager.Load<Texture2D>("Graphic\\Sepia"), this.contentManager.Load<Texture2D>("Graphic\\Sepia_hover"));
            this.filterEntries[2] = new Puzzle_MenuEntry("Filter3", new Vector2(555, 190), this.contentManager.Load<Texture2D>("Graphic\\Oel"), this.contentManager.Load<Texture2D>("Graphic\\Oel_hover"));

            this.gestures = new Puzzle_TouchlessGestures(this, this.rootPointer);

            /*  Fuers Testen  */
            this.touchlessMgr = _mgr;

            //_mgr.CurrentCamera = null;
            this._captureHeight = this.touchlessMgr.CurrentCamera.CaptureHeight;
            this._captureWidth = this.touchlessMgr.CurrentCamera.CaptureWidth;

            this.marker = new Puzzle_TouchlessMarker(this.rootPointer, this.contentManager.Load<Texture2D>("Graphic\\marker"), new Vector2(0, 0));
            this.drawCameraImage = false;
            //initTouchlessManager();       
        }

        public List<Puzzle_PuzzlePiece> getGameImages()
        {
            if (this.gameImages.Count != 0)
            {
                //Puzzle-Teile erstellen
                foreach (Puzzle_Image image in this.gameImages)
                {
                    this.imageProcessing.cutImageIntoPieces(image, this.filterOption, NUMBEROFPIECES);
                    for (int i = 0; i < NUMBEROFPIECES; i++)
                    {
                        this.puzzleList.Add(image.getSpecificImagePiece(i));
                    }
                }
                return this.randomizePuzzleList(); ;
            }
            return null;
        }

        private List<Puzzle_PuzzlePiece> randomizePuzzleList()
        {
            Puzzle_PuzzlePiece[] tempArray = new Puzzle_PuzzlePiece[this.puzzleList.Count];
            Random rand = new Random();
            foreach (Puzzle_PuzzlePiece piece in this.puzzleList)
            {
                bool inserted = false;
                while (!inserted)
                {
                    int randomNumber = rand.Next(0, this.puzzleList.Count);
                    if (tempArray[randomNumber] == null)
                    {
                        tempArray[randomNumber] = piece;
                        inserted = true;
                    }
                }
            }
            return tempArray.ToList<Puzzle_PuzzlePiece>();
        }

        public void keyboardShortcut()
        {
            if (this.gameImages.Count == 0)
            {
                int screenNumber = (int)Math.Ceiling((double)1 / 8);
                String newName = this.imageProcessing.scaleImageDown(IMAGEPATH + "\\new_new_2009-06-10-Hauhechel-Blaeuling_2.jpg");
                this.gameImages.Add(new Puzzle_Image(this.rootPointer, newName, screenNumber));
            }
            this.rootPointer.setIsGaming(true);
        }

        public void reset()
        {
            this.gameImages = null;
            this.puzzleList = null;

            this.gameImages = new List<Puzzle_Image>();
            this.puzzleList = new List<Puzzle_PuzzlePiece>();

            this.showImageScreenNumber = 1;
            this.isFilterMenu = this.isInfoMenu = this.isOptionMenu = false;
            foreach (Puzzle_Image image in this.imageList)
            {
                image.isImageHighlighted = false;
            }
            foreach (Puzzle_MenuEntry entry in this.filterEntries)
            {
                entry.activeEntry = false;
            }
        }

        private void initTouchlessManager()
        {
            //select camera 1
            this.touchlessMgr = new TouchlessMgr();
            foreach (Camera cam in this.touchlessMgr.Cameras)
            {
                if( (cam != null)/* && (cam.ToString().Equals("Logitech Webcam 120"))*/ )
                {
                    this.touchlessMgr.CurrentCamera = cam;
                    this._captureHeight = this.touchlessMgr.CurrentCamera.CaptureHeight;
                    this._captureWidth = this.touchlessMgr.CurrentCamera.CaptureWidth;
                    break;
                }
            }
            
            Bitmap _marker = new Bitmap(MARKERPATH + "marker.bmp");
            this.touchlessMgr.AddMarker("marker", _marker, new System.Drawing.Point(10, 10), 20);
            this.touchlessMgr.Markers[0].Highlight = false;
            this.touchlessMgr.Markers[0].SmoothingEnabled = true;
            this.touchlessMgr.Markers[0].RepresentativeColor = System.Drawing.Color.Green;
            
            if (this.drawCameraImage)
            {
                DrawCameraImage();
            }
        }

        private void DrawCameraImage()
        {
            // display camera image
            this.cameraImage = new Texture2D(this.graphicDeviceManager.GraphicsDevice, this.touchlessMgr.CurrentCamera.CaptureWidth, this.touchlessMgr.CurrentCamera.CaptureHeight);
            this.touchlessMgr.CurrentCamera.OnImageCaptured += new EventHandler<CameraEventArgs>(currentCamera_onImageCaptured);
        }

        private void currentCamera_onImageCaptured(object _sender, CameraEventArgs _event)
        {
            this.cameraImage = this.imageProcessing.convertBmpToTexture2D(_event.Image);
        }

        private void initImagesFromFolder()
        {
            try
            {
                if (Directory.Exists(IMAGEPATH) && Directory.GetFiles(IMAGEPATH) != null)
                {
                    String[] fileNames = Directory.GetFiles(IMAGEPATH);
                    int screenNumber = 1;
                    int count = 1;
                    foreach (String name in fileNames)
                    {
                        screenNumber = (int)Math.Ceiling((double)count / 8);
                        String newName = this.imageProcessing.scaleImageDown(name);
                        this.imageList.Add(new Puzzle_Image(this.rootPointer, newName, screenNumber));
                        //alte Datei löschen
                        if (!name.Equals(newName))
                        {
                            File.Delete(name);
                        }
                        count++;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Es konnte nicht auf den Ordner zugegriffen werden", e.ToString());
            }
            finally { }

            this.imageScreens = (int)Math.Ceiling((double)this.imageList.Count / 8);
        }

        public void Update(GameTime _time)
        {
            this.cameraX = this.touchlessMgr.Markers[0].LastGoodData.X;
            this.cameraY = this.touchlessMgr.Markers[0].LastGoodData.Y;

            this.screenPosX = (this.cameraX * this.graphicDeviceManager.GraphicsDevice.Viewport.Width) / this._captureWidth;
            this.screenPosY = (this.cameraY * this.graphicDeviceManager.GraphicsDevice.Viewport.Height) / this._captureHeight;

            this.screenPosX = this.graphicDeviceManager.GraphicsDevice.Viewport.Width - this.screenPosX;
            //this.screenPosY = this.graphicDeviceManager.GraphicsDevice.Viewport.Height - this.screenPosY;
            
            this.marker.setPosition(new Vector2(this.screenPosX,this.screenPosY));

            if (this.screenPosX != this.graphicDeviceManager.GraphicsDevice.Viewport.Width && this.screenPosY != this.graphicDeviceManager.GraphicsDevice.Viewport.Width)
            {

                this.gestures.addElement(new Puzzle_RawPoint(
                    this.screenPosX,
                    this.screenPosY,
                    (int)_time.TotalGameTime.TotalMilliseconds));
            }

            this.gestures.checkForGestures(_time);
        }

        private void drawBackButton()
        {
            if (this.backEntry[0].getEntryRectangle(true).Intersects(new Microsoft.Xna.Framework.Rectangle(this.screenPosX, this.screenPosY + 25, 1, 1)))
            {
                this.spriteBatch.Draw(this.backEntry[0].getHoverTexture(), this.backEntry[0].getEntryRectangle(true), Microsoft.Xna.Framework.Graphics.Color.White);
            }
            else
            {
                this.spriteBatch.Draw(this.backEntry[0].getTexture(), this.backEntry[0].getEntryRectangle(true), Microsoft.Xna.Framework.Graphics.Color.White);
            }
        }

        public void Draw()
        {
            this.spriteBatch.Begin();
            if (this.drawCameraImage)
            {
                //zum Testen kann das Kamera-Bild dargestellt werden
                this.spriteBatch.Draw(this.cameraImage, this.rootPointer.getViewport(), Microsoft.Xna.Framework.Graphics.Color.White);
            }
            else
            {
                if(this.isOptionMenu)
                {
                    this.spriteBatch.Draw(this.mainBackground, this.rootPointer.getViewport(), Microsoft.Xna.Framework.Graphics.Color.White);
                    int x = 55;
                    int y = 150;
                    int index = (this.showImageScreenNumber - 1) * 8;
                    for (int i = 0; i < 2; i++)
                    {
                        for (int j = 0; j < 4 && index < this.imageList.Count; j++, index++)
                        {
                            this.imageList.ElementAt<Puzzle_Image>(index).setImageRectangle(x, y);
                            this.imageList.ElementAt<Puzzle_Image>(index).ImagePosition = new Vector2(x, y);
                            if (this.imageList.ElementAt<Puzzle_Image>(index).isImageHighlighted)
                            {
                                this.spriteBatch.Draw(this.highlightOptionTexture, new Microsoft.Xna.Framework.Rectangle(
                                    x - 2,
                                    y - 2,
                                    this.highlightOptionTexture.Width,
                                    this.highlightOptionTexture.Height),
                                    Microsoft.Xna.Framework.Graphics.Color.White);
                            }
                            this.imageList.ElementAt<Puzzle_Image>(index).Draw();

                            x += 180;
                        }
                        y += 180;
                        x = 55;
                    }
                    this.drawBackButton();
                }
                else if (this.isFilterMenu)
                {
                    this.spriteBatch.Draw(this.filterBackground, this.rootPointer.getViewport(), Microsoft.Xna.Framework.Graphics.Color.White);
                    foreach(Puzzle_MenuEntry entry in this.filterEntries)
                    {
                        if (entry.activeEntry)
                        {
                            this.spriteBatch.Draw(entry.getHoverTexture(), entry.getEntryRectangle(true), Microsoft.Xna.Framework.Graphics.Color.White);
                        }
                        else
                        {
                            this.spriteBatch.Draw(entry.getTexture(), entry.getEntryRectangle(true), Microsoft.Xna.Framework.Graphics.Color.White);
                        }
                    }
                    this.drawBackButton();
                }
                else if (this.isInfoMenu)
                {
                    this.spriteBatch.Draw(this.infoBackground, this.rootPointer.getViewport(), Microsoft.Xna.Framework.Graphics.Color.White);
                    this.drawBackButton();
                }
                else
                {
                    this.spriteBatch.Draw(this.mainBackground, this.rootPointer.getViewport(), Microsoft.Xna.Framework.Graphics.Color.White);
                    //Menu-Eintraege
                    foreach (Puzzle_MenuEntry entry in this.menuEntries)
                    {
                        if (entry.getEntryRectangle(true).Intersects(new Microsoft.Xna.Framework.Rectangle(this.screenPosX, this.screenPosY+25, 1, 1)))
                        {
                            this.spriteBatch.Draw(entry.getHoverTexture(), entry.getEntryRectangle(true), Microsoft.Xna.Framework.Graphics.Color.White);
                        }
                        else
                        {
                            this.spriteBatch.Draw(entry.getTexture(), entry.getEntryRectangle(true), Microsoft.Xna.Framework.Graphics.Color.White);
                        }
                    }
                }
            }
            //Touchless Marker
            this.marker.Draw();
            this.spriteBatch.End();
        }
    }
}